/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package stud.cp.user.dbaccess;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import stud.cp.core.dbaccess.DAO;
import stud.cp.core.dbaccess.DAOException;
import stud.cp.user.valueobjects.WeaponReference;

/**
 * Класс, описывающий доступ к таблице weapon_references
 * @author Morfant
 */
public class WeaponReferencesDAO implements DAO<WeaponReference> {

    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("CPTNP");
    /**
     * Список названий колонок таблицы weapon_types.
     */
    private static String[] weaponReferencesColumnName = {"weapon_reference_id",
        "weapon_id",
        "reference_weapon_id",
        "property_id"};
    /**
     * Коннект к базе данных.
     */
    private Connection connection = null;

    /**
     * Конструктор, который устанавливает
     * коннект к базе данных.
     * @param connection Связь с базой данных.
     */
    public WeaponReferencesDAO(Connection connection) {
        this.connection = connection;
    }

    /**
     * Зарпос на получения следующего ID.
     * @return Зарпос.
     */
    private String getQueryForSelectNextID() {
        StringBuilder query = new StringBuilder();
        query.append("SELECT weapon_references_seq.NEXTVAL from dual \n");
        return query.toString();
    }

    /**
     * Запрос, позволяющий получить запись по id.
     * @param id ID
     * @return Запрос.
     */
    private String getQueryForGetById(int id) {
        StringBuilder query = new StringBuilder();
        query.append("SELECT weapon_reference_id,weapon_id,reference_weapon_id,property_id \n");
        query.append("FROM weapon_references \n");
        query.append("WHERE weapon_reference_id=");
        query.append(id);
        return query.toString();
    }

    /**
     * Получение данных по ID
     * @param id ID
     * @return Запись.
     * @throws DAOException Ошибка получения данных по ID
     */
    @Override
    public WeaponReference getById(int id) throws DAOException {
        WeaponReference weaponReference = null;
        ResultSet set = null;
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(getQueryForGetById(id));
            set = prestat.executeQuery();
            if (set.next()) {
                weaponReference =
                        new WeaponReference(set.getInt(weaponReferencesColumnName[0]),
                        set.getInt(weaponReferencesColumnName[1]),
                        set.getInt(weaponReferencesColumnName[2]),
                        set.getInt(weaponReferencesColumnName[3]));
            }
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка получения данных по ID", ex);
        } finally {
            logger.debug("SQL: \n " + getQueryForGetById(id));
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
        return weaponReference;
    }

    /**
     * Запрос, позволяющий получить запись по id.
     * @param id ID
     * @return Запрос.
     */
    private String getQueryForGetByWeaponIdAndPropertyID(int weaponId, int propertyId) {
        StringBuilder query = new StringBuilder();
        query.append("SELECT weapon_reference_id,weapon_id,reference_weapon_id,property_id \n");
        query.append("FROM weapon_references \n");
        query.append("WHERE weapon_id=");
        query.append(weaponId);
        query.append("\n AND property_id=");
        query.append(propertyId);
        return query.toString();
    }

    /**
     * Получение данных по ID
     * @param id ID
     * @return Запись.
     * @throws DAOException Ошибка получения данных по ID
     */
    public WeaponReference getByWeaponIDAndPropertyID(int weaponId, int propertyId) throws DAOException {
        WeaponReference weaponReference = null;
        ResultSet set = null;
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(getQueryForGetByWeaponIdAndPropertyID(weaponId, propertyId));
            set = prestat.executeQuery();
            if (set.next()) {
                weaponReference =
                        new WeaponReference(set.getInt(weaponReferencesColumnName[0]),
                        set.getInt(weaponReferencesColumnName[1]),
                        set.getInt(weaponReferencesColumnName[2]),
                        set.getInt(weaponReferencesColumnName[3]));
            }
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка получения данных по ID", ex);
        } finally {
            logger.debug("SQL: \n " + getQueryForGetByWeaponIdAndPropertyID(weaponId, propertyId));
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
        return weaponReference;
    }

    /**
     * Запрос на обновление записи в таблице.
     * @param weapon_reference_id ID
     * @param weapon_id Имя
     * @return Запрос.
     */
    private String getQueryForUpdate(Integer weapon_reference_id, Integer weapon_id, Integer reference_weapon_id, Integer property_id) {
        StringBuilder query = new StringBuilder();
        query.append("UPDATE weapon_references \n");
        query.append("SET weapon_id=");
        query.append(weapon_id);
        query.append(", \n");
        query.append("reference_weapon_id=");
        query.append(reference_weapon_id);
        query.append(", \n");
        query.append("property_id=");
        query.append(property_id);
        query.append(" \n");
        query.append("WHERE weapon_reference_id=");
        query.append(weapon_reference_id);
        return query.toString();
    }

    /**
     * Метод, отвечающий за обновление данных.
     * @param entry Запись.
     * @throws DAOException Ошибка при обновление данных.
     */
    @Override
    public void update(WeaponReference entry) throws DAOException {
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(
                    getQueryForUpdate(
                    entry.getWeapon_reference_id(),
                    entry.getWeapon_id(),
                    entry.getReference_weapon_id(),
                    entry.getProperty_id()));
            prestat.executeUpdate();
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка обновлени данных.", ex);
        } finally {
            logger.debug("SQL: \n " + getQueryForUpdate(
                    entry.getWeapon_reference_id(),
                    entry.getWeapon_id(),
                    entry.getReference_weapon_id(),
                    entry.getProperty_id()));
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
    }

    /**
     * Запрос на добавление
     * новой записи в таблицу.
     * @param weapon_reference_id ID
     * @param weapon_id Имя
     * @return Запрос.
     */
    private String getQueryForInsert(Integer weapon_reference_id, Integer weapon_id, Integer reference_weapon_id, Integer property_id) {
        StringBuilder query = new StringBuilder();
        query.append("INSERT INTO weapon_references(weapon_reference_id,weapon_id,reference_weapon_id,property_id) \n");
        query.append("VALUES(");
        query.append(weapon_reference_id);
        query.append(",");
        query.append(weapon_id);
        query.append(",");
        query.append(reference_weapon_id);
        query.append(",");
        query.append(property_id);
        query.append(")");
        return query.toString();
    }

    /**
     * Зарпос на получения максимального id из таблицы.
     * @return Зарпос.
     */
    private String getQueryForSelectMaxId() {
        StringBuilder query = new StringBuilder();
        query.append("SELECT MAX(weapon_reference_id) \n");
        query.append("FROM weapon_references");
        return query.toString();
    }

    /**
     * Метод, который создает новую запись в таблице.
     * @param entry Запись.
     * @throws DAOException Ошибка создания новой записи.
     */
    @Override
    public int create(WeaponReference entry) throws DAOException {
        ResultSet set = null;
        PreparedStatement prestat = null;
        Integer index = null;
        try {
            prestat = connection.prepareStatement(getQueryForSelectNextID());
            set = prestat.executeQuery();

            if (set.next()) {
                index = set.getInt(1) ;
            } else {
                index = 0;
            }
            prestat.close();
            prestat =
                    connection.prepareStatement(
                    getQueryForInsert(index, entry.getWeapon_id(),
                    entry.getReference_weapon_id(),
                    entry.getProperty_id()));
            prestat.executeUpdate();
            return index;
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка при создание записи.", ex);
        } finally {
            logger.debug("SQL: \n " + getQueryForSelectMaxId());
            logger.debug("SQL: \n " + getQueryForInsert(index, entry.getWeapon_id(),
                    entry.getReference_weapon_id(),
                    entry.getProperty_id()));
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
    }

    /**
     * Запрос, позволяющий при выполнении
     * получить полностью данные из таблицы
     * weapon_types.
     * @return Строка запроса.
     */
    private String getQuerytForAllWeaponReference() {
        StringBuilder query = new StringBuilder();
        query.append("select weapon_reference_id,weapon_id,reference_weapon_id,property_id \n");
        query.append("from weapon_references");
        return query.toString();
    }

    /**
     * Метод, выдающий список всех записей.
     * @return Список записей.
     * @throws DAOException Ошибка получения данных.
     */
    @Override
    public List<WeaponReference> getAll() throws DAOException {
        List<WeaponReference> data_list = new LinkedList<WeaponReference>();
        ResultSet set = null;
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(getQuerytForAllWeaponReference());
            set = prestat.executeQuery();
            while (set.next()) {
                data_list.add(new WeaponReference(set.getInt(weaponReferencesColumnName[0]),
                        set.getInt(weaponReferencesColumnName[1]),
                        set.getInt(weaponReferencesColumnName[2]),
                        set.getInt(weaponReferencesColumnName[3])));
            }
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка получения списка данных.", ex);
        } finally {
            logger.debug("SQL: \n " + getQuerytForAllWeaponReference());
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
        return data_list;
    }

    /**
     * Запрос, позволяющий при выполнении
     * получить полностью данные из таблицы
     * weapon_types.
     * @return Строка запроса.
     */
    private String getQueryForAllReferenceForWeapon(int weapon_id) {
        StringBuilder query = new StringBuilder();
        query.append("select weapon_reference_id,weapon_id,reference_weapon_id,property_id \n");
        query.append("from weapon_references \n");
        query.append("where weapon_id=");
        query.append(weapon_id);
        return query.toString();
    }

    /**
     * Метод, выдающий список всех записей.
     * @return Список записей.
     * @throws DAOException Ошибка получения данных.
     */
    public List<WeaponReference> getAllReferenceForWeapon(int weapon_id) throws DAOException {
        List<WeaponReference> data_list = new LinkedList<WeaponReference>();
        ResultSet set = null;
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(getQueryForAllReferenceForWeapon(weapon_id));
            set = prestat.executeQuery();
            while (set.next()) {
                data_list.add(new WeaponReference(set.getInt(weaponReferencesColumnName[0]),
                        set.getInt(weaponReferencesColumnName[1]),
                        set.getInt(weaponReferencesColumnName[2]),
                        set.getInt(weaponReferencesColumnName[3])));
            }
        } catch (SQLException ex) {
            logger.debug("DAO_propety_group", ex);
            throw new DAOException("Ошибка получения списка данных.", ex);
        } finally {
            logger.debug("SQL: \n " + getQuerytForAllWeaponReference());
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
        return data_list;
    }

    /**
     * Зарпос на удаление из таблицы
     * записи по id.
     * @param id ID
     * @return Зарпос.
     */
    private String getQueryForDelete(int id) {
        StringBuilder query = new StringBuilder();
        query.append("DELETE FROM weapon_references \n");
        query.append("WHERE weapon_reference_id=");
        query.append(id);
        return query.toString();
    }

    /**
     * Метод, позволяющий удалять данные по записи.
     * @param id Запись.
     * @throws DAOException
     */
    @Override
    public void delete(int id) throws DAOException {
        PreparedStatement prestat = null;
        try {
            prestat = connection.prepareStatement(getQueryForDelete(id));
            prestat.executeUpdate();
        } catch (SQLException ex) {
            logger.debug("DAO_propeties", ex);
            throw new DAOException("Ошибка удаления данных.", ex);
        } finally {
            logger.debug("SQL: \n " + getQueryForDelete(id));
            if (prestat != null) {
                try {
                    prestat.close();
                } catch (SQLException ex) {
                    logger.debug("DAO_propety", ex);
                    throw new DAOException("Ошибка закрытия ResultSet`а.", ex);
                }
            }
        }
    }
}
